package top.cardone.mapper;

import com.google.gson.Gson;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializer;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.FactoryBean;
import top.cardone.context.util.DateUtils;

import java.util.Date;

/**
 * Created by yao hai tao on 2015/8/20.
 */
public class GsonFactoryBean implements FactoryBean<Gson> {
	@lombok.Setter
	private String datePattern = "yyyy-MM-dd HH:mm:ss";

	@lombok.Setter
	private Boolean enableComplexMapKeySerialization = true;

	@lombok.Setter
	private Boolean isSetPrettyPrinting = true;

	@lombok.Setter
	@lombok.Getter
	private Class<?> objectType = Gson.class;

	@lombok.Setter
	private Boolean serializeNulls = true;

	@lombok.Setter
	@lombok.Getter
	private boolean singleton = true;

	private Gson object;

	@Override
	public Gson getObject() throws Exception {
		if (BooleanUtils.isTrue(singleton) && object != null) {
			return object;
		}

		com.google.gson.GsonBuilder gsonBuilder = new com.google.gson.GsonBuilder();

		if (BooleanUtils.isTrue(enableComplexMapKeySerialization)) {
			gsonBuilder = gsonBuilder.enableComplexMapKeySerialization();
		}

		if (BooleanUtils.isTrue(serializeNulls)) {
			gsonBuilder = gsonBuilder.serializeNulls();
		}

		if (BooleanUtils.isTrue(isSetPrettyPrinting)) {
			gsonBuilder = gsonBuilder.setPrettyPrinting();
		}

		gsonBuilder = gsonBuilder.registerTypeAdapter(String.class, (JsonSerializer<String>) (src, typeOfSrc, context) -> new JsonPrimitive(StringUtils.defaultString(src, StringUtils.EMPTY)));

		gsonBuilder = gsonBuilder.registerTypeAdapter(Date.class, (JsonDeserializer<Date>) (json, typeOfT, context) -> StringUtils.isBlank(json.getAsString()) ? null : DateUtils.parseDate(json.getAsString()));

		gsonBuilder = gsonBuilder.registerTypeAdapter(Integer.class, (JsonDeserializer<Integer>) (json, typeOfT, context) -> StringUtils.isBlank(json.getAsString()) ? null : NumberUtils.toInt(json.getAsString()));

		gsonBuilder = gsonBuilder.registerTypeAdapter(Double.class, (JsonDeserializer<Double>) (json, typeOfT, context) -> StringUtils.isBlank(json.getAsString()) ? null : NumberUtils.toDouble(json.getAsString()));

		gsonBuilder = gsonBuilder.registerTypeAdapter(Long.class, (JsonDeserializer<Long>) (json, typeOfT, context) -> StringUtils.isBlank(json.getAsString()) ? null : NumberUtils.toLong(json.getAsString()));

		gsonBuilder = gsonBuilder.registerTypeAdapter(Float.class, (JsonDeserializer<Float>) (json, typeOfT, context) -> StringUtils.isBlank(json.getAsString()) ? null : NumberUtils.toFloat(json.getAsString()));

		gsonBuilder = gsonBuilder.registerTypeAdapter(Short.class, (JsonDeserializer<Short>) (json, typeOfT, context) -> StringUtils.isBlank(json.getAsString()) ? null : NumberUtils.toShort(json.getAsString()));

		gsonBuilder = gsonBuilder.setDateFormat(StringUtils.defaultIfBlank(datePattern, DateFormatUtils.ISO_DATE_FORMAT.getPattern()));

		object = gsonBuilder.create();

		return object;
	}
}
